package cn.itcast.controller;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.CookieValue;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;

import cn.itcast.pojo.User;
import cn.itcast.pojo.UsersVO;

/**
 * springmvc的配置步骤： 1、在web.xml中配置前端控制器DispatcherServlet: 配置tomcat启动时初始化
 * 配置springmvc配置文件的路径
 * 
 * 2、创建自定义处理器，在其中可以通过ModelAndView封装需要响应的页面以及数据
 * 
 * 3、在springmvc的配置文件中开启包扫描
 * 
 * @author zhang
 *
 */
@Controller
@RequestMapping("hello")
public class HelloController {

	@RequestMapping("show1")
	public ModelAndView test1() {
		// 是用来封装响应的页面以及数据的
		ModelAndView mv = new ModelAndView();
		// 设置要响应的页面
		// mv.setViewName("/WEB-INF/views/hello.jsp");
		mv.setViewName("hello");
		// 设置数据:将数据存入了request域中
		mv.addObject("msg", "这是第一个springmvc的程序");

		return mv;
	}

	@RequestMapping("show2asdf")
	public ModelAndView test2() {
		ModelAndView mv = new ModelAndView();
		mv.setViewName("hello");
		mv.addObject("msg", "使用？:表示任意单个字符");

		return mv;
	}

	@RequestMapping("*/show3")
	public ModelAndView test3() {
		ModelAndView mv = new ModelAndView();
		mv.setViewName("hello");
		mv.addObject("msg", "使用*:表示任意多个字符");

		return mv;
	}

	@RequestMapping("show4/**")
	public ModelAndView test4() {
		ModelAndView mv = new ModelAndView();
		mv.setViewName("hello");
		mv.addObject("msg", "使用**:表示任意多级路径");

		return mv;
	}

	@RequestMapping("show5/{name}/{id}")
	public ModelAndView test5(@PathVariable("name") String name,
			@PathVariable("id") Long id) {
		ModelAndView mv = new ModelAndView();
		mv.setViewName("hello");
		mv.addObject("msg", "rest风格的映射:" + name + "..." + id);

		return mv;
	}

	@RequestMapping(value = "show6", method = RequestMethod.POST)
	public ModelAndView test6() {
		ModelAndView mv = new ModelAndView();
		mv.setViewName("hello");
		mv.addObject("msg", "限定请求方法的映射:post");

		return mv;
	}

	@RequestMapping(value = "show7", method = { RequestMethod.POST,
			RequestMethod.GET })
	public ModelAndView test7() {
		ModelAndView mv = new ModelAndView();
		mv.setViewName("hello");
		mv.addObject("msg", "限定请求方法的映射:post和get");

		return mv;
	}

	@RequestMapping(value = "show8", params = "userId")
	public ModelAndView test8() {
		ModelAndView mv = new ModelAndView();
		mv.setViewName("hello");
		mv.addObject("msg", "限定请求参数的映射:userId");

		return mv;
	}

	@RequestMapping(value = "show9", params = "!userId")
	public ModelAndView test9() {
		ModelAndView mv = new ModelAndView();
		mv.setViewName("hello");
		mv.addObject("msg", "限定请求参数的映射:必须不能携带参数userId");

		return mv;
	}

	@RequestMapping(value = "show10", params = "userId=101")
	public ModelAndView test10() {
		ModelAndView mv = new ModelAndView();
		mv.setViewName("hello");
		mv.addObject("msg", "限定请求参数的映射:必须携带参数userId=101");

		return mv;
	}

	@RequestMapping(value = "show11", params = "userId!=101")
	public ModelAndView test11() {
		ModelAndView mv = new ModelAndView();
		mv.setViewName("hello");
		mv.addObject("msg", "限定请求参数的映射:必须携带参数不能为userId=101");

		return mv;
	}

	@RequestMapping(value = "show12", params = { "name=lisi", "userId!=100" })
	public ModelAndView test12() {
		ModelAndView mv = new ModelAndView();
		mv.setViewName("hello");
		mv.addObject("msg", "限定请求参数的映射:必须携带参数为userId和name");

		return mv;
	}

	@GetMapping("show13")
	public ModelAndView test13() {
		ModelAndView mv = new ModelAndView();
		mv.setViewName("hello");
		mv.addObject("msg", "组合注解的使用：get");

		return mv;
	}

	@PostMapping("show14")
	public ModelAndView test14() {
		ModelAndView mv = new ModelAndView();
		mv.setViewName("hello");
		mv.addObject("msg", "组合注解的使用：post");

		return mv;
	}

	@PutMapping("show15")
	public ModelAndView test15() {
		ModelAndView mv = new ModelAndView();
		mv.setViewName("hello");
		mv.addObject("msg", "组合注解的使用：put");

		return mv;
	}

	@DeleteMapping("show16")
	public ModelAndView test16() {
		ModelAndView mv = new ModelAndView();
		mv.setViewName("hello");
		mv.addObject("msg", "组合注解的使用：delete");

		return mv;
	}

	/**
	 * 该方法的返回值就是视图的名称
	 * 
	 * @param model
	 * @return
	 */
	@RequestMapping("show17")
	public String test17(Model model) {
		// 在request域中添加了数据
		model.addAttribute("msg", "优化的方法");
		return "hello";// 就是视图名称
	}

	
	@RequestMapping("show18")
	@ResponseStatus(value = HttpStatus.OK)
	// 响应200状态码
	public void test18() {
		System.out.println("返回值是void的方法");
	}

	
	@RequestMapping("show19")
	public String test19(Model model, HttpServletRequest request,
			HttpServletResponse response, HttpSession session) {

		model.addAttribute("msg", request + "</br>" + response + "</br>"
				+ session);

		return "hello";
	}

	/**
	 * @RequestParam(value="name"):name表示获取的参数的名称，如果只有一个value属性的话， 
	 *                                                             默认另外一个属性required
	 *                                                             =true,
	 *                                                             就是指参数必须携带name
	 *                                                             defaultValue
	 *                                                             :如果参数没有数据
	 *                                                             ，就设置一个默认值
	 *                                                             ,一旦使用了该属性
	 *                                                             ，那么required
	 *                                                             =true就失效了。
	 * @param model
	 * @param name
	 * @return
	 */
	@RequestMapping("show20")
	public String test20(
			Model model,
			@RequestParam(value = "name", required = true, defaultValue = "wangwu") String name) {
		model.addAttribute("msg", name);
		return "hello";
	}

	/**
	 * 获取cookie中的JSESSIONID
	 */
	@RequestMapping("show21")
	public String test21(Model model, HttpServletRequest request) {

		Cookie[] cookies = request.getCookies();
		if (cookies != null) {
			for (Cookie cookie : cookies) {
				if (cookie.getName().equals("JSESSIONID")) {
					model.addAttribute("msg", cookie.getValue());
				}
			}
		}
		return "hello";
	}


	@RequestMapping("show22")
	public String test22(
			Model model,
			@CookieValue(value = "JSESSIONID", required = false) String jsessionid) {

		model.addAttribute("msg", jsessionid);

		return "hello";
	}

	@RequestMapping("show23")
	public String test23(Model model, @RequestParam("name") String name,
			@RequestParam("age") Integer age,
			@RequestParam("isMarry") Boolean isMarry,
			@RequestParam("income") Float income,
			@RequestParam("interests") String[] interests) {

		model.addAttribute("msg", name + "</br>" + age + "</br>" + isMarry
				+ "</br>" + income + "</br>" + Arrays.toString(interests));

		return "hello";
	}
	
	@RequestMapping("show24")
	public String test24(Model model,User user,@RequestParam("name")String name){
		
		model.addAttribute("msg", user+"..."+name);
		return "hello";
	}
	/**
	 * 获取集合类型的数据
	 * @param model
	 * @param ids
	 * @return
	 */
	@RequestMapping("show25")
	public String test25(Model model,@RequestParam("ids")List<Long> ids){
		model.addAttribute("msg", ids);
		
		return "hello";
	}
	
	/**
	 * VO:称之为值对象
	 * PO:持久化对象
	 * POJO:普通的java对象
	 * @param model
	 * @param userVO
	 * @return
	 */
	@RequestMapping("show26")
	public String test26(Model model,UsersVO userVO ){
		
		model.addAttribute("msg", userVO);
		
		return "hello";
	}
	
	@RequestMapping("show27")
	public String test27(Model model){
		
		List<User> list = new ArrayList<User>();
		
		for (int i = 0; i < 20; i++) {
			User user = new User();
			user.setId(i+1l);
			user.setUserName("admin"+i);
			user.setName("用户"+i);
			user.setAge(18+i);
			list.add(user);
		}
		model.addAttribute("users", list);
		
		return "userList";
	}
	
	@RequestMapping("show28")
	@ResponseBody//该注解的作用：将方法的返回值，响应为json格式的数据
	public List<User> test28(Model model){
		
		List<User> list = new ArrayList<User>();
		
		for (int i = 0; i < 20; i++) {
			User user = new User();
			user.setId(i+1l);
			user.setUserName("admin"+i);
			user.setName("用户"+i);
			user.setAge(18+i);
			list.add(user);
		}
		model.addAttribute("users", list);
		
		return list;
	}
	
	@RequestMapping("show29")
	public String test29(Model model,@RequestBody() User user){
		
		model.addAttribute("msg", user);
		
		return "hello";
		
	}
	@RequestMapping("show30")
	public String test30(Model model,@RequestBody() String user){
		
		model.addAttribute("msg", user);
		
		return "hello";
		
	}
	
	/**
	 * 文件上传
	 * @throws IOException 
	 * @throws IllegalStateException 
	 */
	@RequestMapping("show31")
	public String test31(Model model,@RequestParam("file") MultipartFile file) throws IllegalStateException, IOException{
		
		if (file!=null) {
			file.transferTo(new File("d:/upload/"+file.getOriginalFilename()));
		}
		model.addAttribute("msg", "上传成功");
		return "hello";
	}
	
	/**
	 * 斜杠：表示http://localhost:8080/
	 * 没有斜杠：表示http://localhost:8080/hello/
	 * @return
	 */
	@RequestMapping("show32")
	public String test32(){
		System.out.println("show32");
		return "forward:show34.do?type=forward";
	}
	
	@RequestMapping("show33")
	public String test33(){
		System.out.println("show33");
		return "redirect:show34.do?type=redirect";
	}
	
	
	@RequestMapping("show34")
	public String test34(Model model,@RequestParam("type")String type){
		model.addAttribute("msg", type);
		return "hello";
	}
	
	@RequestMapping("show35")
	public String test35(Model model){
		System.out.println("show35执行了");
		return "hello";
	}
	
	
	@RequestMapping("show36")
	public String test36(@RequestParam("name") String name) {
		System.out.println(name);
		return "hello";
	}
}
